package com.yalu.read.pdf.bill;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.yalu.entity.SaleData;
import lombok.val;
import org.apache.pdfbox.io.RandomAccessFile;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class BillOnePdfRead {

    /**
     * 测试pdf文件的创建
     *
     * @param args
     */
    public static void main(String[] args) {
        String filePath = "D://yalu//bill//";  //这里先手动把绝对路径的文件夹给补上。
        List<String> filePaths = new ArrayList<>();
        recursionFile(filePath, filePaths);
        System.out.println("文件数量：" + filePaths.size());
        List<SaleData> list = new ArrayList<>();
        String year = filePath.replaceAll("D://yalu//", "").replaceAll("//", "");
        System.out.println(year);
        for (String fileName : filePaths) {
            readPdf(fileName, list);
        }
        String outFileName = "D:\\yalu\\对账单.xlsx";
        writerFils(list, outFileName);
    }

    /**
     * 读PDF文件，使用了pdfbox开源项目
     *
     * @param fileName
     */
    public static void readPdf(String fileName, List<SaleData> list) {
        File file = new File(fileName);
        FileInputStream in = null;
        try {
            in = new FileInputStream(fileName);
            // 新建一个PDF解析器对象
            PDFParser parser = new PDFParser(new RandomAccessFile(file, "r"));
            // 对PDF文件进行解析
            parser.parse();
            // 获取解析后得到的PDF文档对象
            PDDocument pdfdocument = parser.getPDDocument();
            int pageSize = pdfdocument.getNumberOfPages();
            for (int i = 0; i < pageSize; i++) {
                // 新建一个PDF文本剥离器
                PDFTextStripper stripper = new PDFTextStripper();
                // 设置按顺序输出
                stripper.setSortByPosition(true);
                stripper.setStartPage(i + 1);
                stripper.setEndPage(i + 1);
                String lineSepartor = stripper.getLineSeparator();
                // 从PDF文档对象中剥离文本
                String result = stripper.getText(pdfdocument);
                String[] resultArray = result.split(lineSepartor);
                int arrayLength = resultArray.length;
                Queue<SaleData> dataQueue = new LinkedList<>();
                for (int y = 0; y < arrayLength; y++) {
                    SaleData dataNow = dataQueue.poll();
                    SaleData saleData = new SaleData();
                    if (null != dataNow) {
                        BeanUtils.copyProperties(dataNow, saleData);
                    }
                    String lineText = resultArray[y];
                    if (StringUtils.hasText(lineText) && lineText.contains("DATE:")) {
                        final val lintTextArray = lineText.split(":");
                        saleData.setDate(lintTextArray.length < 3 ? lintTextArray[1] : lintTextArray[2]);
                        dataQueue.offer(saleData);
                    } else if (StringUtils.hasText(lineText) && lineText.contains("INVOICE NO.:")) {
                        final val lintTextArray = lineText.split(":");
                        saleData.setSaleNo(lintTextArray[1]);
                        dataQueue.offer(saleData);
                    } else if (StringUtils.hasText(lineText) && (lineText.contains("BUYER COMPANY:"))) {
                        final val lintTextArray = lineText.split(":");
                        saleData.setName(lintTextArray.length > 1 ? lintTextArray[1] : "未取到数据");
                        dataQueue.offer(saleData);
                    } else if (StringUtils.hasText(lineText) && lineText.contains("Total price")) {
                        final val lintTextArray = lineText.split("Total price");
                        saleData.setAmount(lintTextArray[1]);
                        dataQueue.offer(saleData);
                    } else if (StringUtils.hasText(lineText) && lineText.contains("PayPal amount (5% fee)")) {
                        final val lintTextArray = lineText.split("fee");
                        saleData.setTotal(lintTextArray[1].replace(")", ""));
                        dataQueue.offer(saleData);
                    } else if (StringUtils.hasText(lineText) && lineText.contains("AMOUNT (")) {
                        final val lintTextArray = lineText.split("AMOUNT");
                        saleData.setCurrency(lintTextArray[1].replace(" (", "").replace(")    ）", ""));
                        dataQueue.offer(saleData);
                    } else {
                        dataQueue.offer(saleData);
                    }
                    if (StringUtils.hasText(saleData.getAmount()) && StringUtils.hasText(saleData.getTotal()) && StringUtils.hasText(saleData.getDate()) && StringUtils.hasText(saleData.getSaleNo())) {
                        saleData.setFileName(file.getName());
                        list.add(saleData);
                        dataQueue.poll();
                        break;
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("读取PDF文件" + file.getAbsolutePath() + "生失败！" + e);
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e1) {
                }
            }
        }
    }

    /**
     * 写入文件
     *
     * @param data
     * @param outFileName
     */
    public static void writerFils(List<SaleData> data, String outFileName) {
        try {
            ExcelWriter excelWriter = EasyExcel.write(outFileName, SaleData.class).build();
            String sheetName = "1";
            WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
            excelWriter.write(data, writeSheet);
            // 千万别忘记finish 会帮忙关闭流
            excelWriter.finish();
        } catch (Exception e) {
            System.out.println("文件写入失败：" + e.getMessage());
        }
    }

    /**
     * 递归文件
     *
     * @param path
     * @param filePaths
     */
    public static void recursionFile(String path, List<String> filePaths) {
        if (StringUtils.hasText(path)) {
            File file = new File(path);
            for (File f : file.listFiles()) {
                if (f.isDirectory()) {
                    recursionFile(f.getPath(), filePaths);
                } else {
                    if (f.getPath().toLowerCase().contains(".pdf")) {
                        filePaths.add(f.getPath());
                    }
                }
            }
        }
    }

}
